package com.ruoyi.app.controller.member.controller;

import com.ruoyi.app.common.utils.JwtUtil;
import com.ruoyi.app.controller.common.entity.SmsBO;
import com.ruoyi.app.controller.member.entity.BO.AppletAuthBO;
import com.ruoyi.app.controller.member.entity.BO.MemberDetailBO;
import com.ruoyi.app.controller.member.entity.BO.MemberVipTypeUpgradeBO;
import com.ruoyi.app.controller.member.entity.VO.MemberConsumeSearchVO;
import com.ruoyi.app.controller.member.entity.VO.MemberConsumeVO;
import com.ruoyi.app.controller.member.service.IAppletService;
import com.ruoyi.app.controller.member.service.IMemberService;
import com.ruoyi.app.controller.member.service.IMemberVipTypeService;
import com.ruoyi.app.controller.shop.mapper.IShopConfigMapper;
import com.ruoyi.app.framework.base.BaseAppController;
import com.ruoyi.common.annotation.AuthMember;
import com.ruoyi.common.annotation.ParseShopId;
import com.ruoyi.common.annotation.PassToken;
import com.ruoyi.common.constant.MemberConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.VO.member.MemberBalanceRecordSearchVO;
import com.ruoyi.common.entity.VO.member.MemberCreditRecordSearchVO;
import com.ruoyi.common.entity.VO.member.MemberVO;
import com.ruoyi.common.entity.VO.member.MemberVipTypeVO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.Md5Utils;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 会员管理
 */
@RestController
@RequestMapping("/api/member")
public class MemberController extends BaseAppController {

    @Value("${applet.salt}")
    private String salt;

    @Value("${api.host}")
    private String host;

    @Resource
    private IMemberService memberService;

    @Resource
    private IMemberVipTypeService memberVipTypeService;

    @Resource
    private IAppletService appletService;

    @Resource
    private IShopConfigMapper shopConfigMapper;

    /**
     * 基础授权
     */
    @PostMapping("/appletAuth")
    @PassToken
    public AjaxResult appletAuth(@ApiIgnore @ParseShopId Long shopId, @Valid @RequestBody AppletAuthBO appletAuthBO, BindingResult results) {
        if (results.hasErrors()) {
            return error(results.getFieldError().getDefaultMessage());
        }
        appletAuthBO.setShopId(shopId);
        MemberDO member = appletService.auth(appletAuthBO);
        if (member != null) {
            String token = JwtUtil.sign(member.getOpenid(), member.getId(), member.getShopId(), member.getId() + salt);
            return AjaxResult.success("授权登录成功!", token);
        } else {
            return error("授权登录失败！");
        }
    }

    /**
     * 手机号授权
     */
    @PostMapping("/appletPhoneAuth")
    @PassToken
    public AjaxResult appletPhoneAuth(@ParseShopId Long shopId, @AuthMember MemberDO member, @Valid @RequestBody AppletAuthBO appletAuthBO, BindingResult results) {
        if (results.hasErrors()) {
            return error(results.getFieldError().getDefaultMessage());
        }
        appletAuthBO.setShopId(shopId);
        MemberDO memberInfo = appletService.phoneAuth(appletAuthBO, member.getId());
        if (memberInfo != null) {
            String token = JwtUtil.sign(memberInfo.getOpenid(), memberInfo.getId(), memberInfo.getShopId(), memberInfo.getId() + salt);
            return AjaxResult.success("授权登录成功!", token);
        } else {
            return error("授权登录失败！");
        }
    }

    @ApiOperation(value = "获取会员档案", notes = "包含头像、昵称、手机号、真实姓名、性别、生日")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "授权密钥", required = true, dataTypeClass = String.class, paramType = "header"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = ""),
            @ApiResponse(code = 500, message = "登录超时！")
    })
    @GetMapping("/profile")
    public AjaxResult profile(@ApiIgnore @AuthMember MemberDO member) {
        MemberVO memberInfo = memberService.getProfileById(member.getId());
        if (memberInfo != null) {
            // 默认头像处理
            String avatarW = host + "/logo/avatar-w.png";
            String avatarDefault = host + "/logo/avatar.png";
            if (memberInfo.getAvatar().equals(avatarDefault)) {
                memberInfo.setAvatarW(avatarW);
            } else {
                memberInfo.setAvatarW(memberInfo.getAvatar());
            }
            return AjaxResult.success(memberInfo);
        } else {
            return error("沒有找到该会员信息！");
        }
    }

    @ApiOperation(value = "获取会员资产", notes = "余额，积分，佣金，优惠券数量")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "授权密钥", required = true, dataTypeClass = String.class, paramType = "header"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = ""),
            @ApiResponse(code = 500, message = "登录超时！")
    })
    @GetMapping("/asset")
    public AjaxResult asset(@AuthMember MemberDO memberDO) {
        MemberDetailBO memberAsset = memberService.getAssetById(memberDO.getId());
        if (memberAsset != null) {
            return AjaxResult.success(memberAsset);
        } else {
            return error("沒有找到该会员信息！");
        }
    }

    /**
     * 获取会员详细信息 包含当天油价
     * 页面 [我的]
     */
    @GetMapping("/detail")
    public AjaxResult detail(@ApiIgnore @AuthMember MemberDO member) {
        MemberDetailBO memberInfo = memberService.getDetailById(member.getId());
        if (memberInfo != null) {
            return AjaxResult.success(memberInfo);
        } else {
            return error("沒有找到该会员信息！");
        }
    }

    @ApiOperation(value = "获取会员升级信息", notes = "首页的？里面需要调用")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "授权密钥", required = true, dataTypeClass = String.class, paramType = "header"),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = ""),
            @ApiResponse(code = 500, message = "登录超时！")
    })
    @GetMapping("/upgradeInfo")
    public AjaxResult upgradeInfo(@ApiIgnore @AuthMember MemberDO member) {
        MemberDetailBO memberAsset = memberService.getAssetById(member.getId());
        if (memberAsset != null) {
            MemberVipTypeUpgradeBO upgradeInfo = memberVipTypeService.getUpgradeInfoById(memberAsset.getVipTypeId(), memberAsset.getTotalRechargeAmount(), memberAsset.getTotalPetrolAmount());
            return AjaxResult.success(upgradeInfo);
        } else {
            return error("沒有找到该会员信息！");
        }
    }

    @ApiOperation(value = "支付密码修改", notes = "支付密码，支付密码确认，短信验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "登录授权", value = "token", required = true, dataTypeClass = String.class, paramType = "header"),
            @ApiImplicitParam(name = "短信验证码", value = "code", required = true, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "支付密码(md5加密)", value = "payPassword", required = true, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "支付密码确认", value = "confirmPayPassword", required = true, dataTypeClass = String.class, paramType = "query")
    })
    @PostMapping("/updatePayPassword")
    public AjaxResult updatePayPassword(@RequestBody Map map, @AuthMember MemberDO member) {
        if (!map.containsKey("payPassword") || !map.containsKey("confirmPayPassword")) {
            throw new BusinessException("请填写支付密码及确认支付密码");
        }
        if (!map.containsKey("code")) {
            throw new BusinessException("请填写短信验证码");
        }
        if (map.containsKey("payPassword") != map.containsKey("confirmPayPassword")) {
            throw new BusinessException("支付密码与确认支付密码不一致");
        }
        SmsBO smsBO = new SmsBO();
        smsBO.setCode(map.get("code").toString());
//        smsBO.setFlag(AliYunSmsConstants.TemplateEnum.MODIFY_PAY_PASSWORD.getRedisPrefix());
        smsBO.setPhone(member.getPhone());
//        smsService.verify(smsBO);
        MemberDO memberPasswordInfo = memberService.getPasswordInfoById(member.getId());
        String payPassword = Md5Utils.getSalt(map.get("payPassword").toString(), memberPasswordInfo.getSalt());
        memberPasswordInfo = new MemberDO();
        memberPasswordInfo.setId(member.getId());
        memberPasswordInfo.setPaypassword(payPassword);
        memberPasswordInfo.setUpdateTime(new Date());
        memberService.updatePrivate(memberPasswordInfo);
        return AjaxResult.success("支付密码修改成功！");
    }

    /**
     * 修改会员资料
     *
     * @param member
     * @param memberVO
     * @param results
     * @return
     */
    @PostMapping("/updateProfile")
    public AjaxResult updateProfile(@ApiIgnore @AuthMember MemberDO member, @Valid @RequestBody MemberVO memberVO, BindingResult results) {
        if (results.hasErrors()) {
            return error(results.getFieldError().getDefaultMessage());
        }
        memberVO.setId(member.getId());
        memberService.updateProfile(memberVO);
        return success("保存成功！");
    }

    @ApiOperation(value = "余额变动记录", notes = "获取会员余额变动记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登录密钥", required = true, dataTypeClass = String.class, paramType = "header"),
            @ApiImplicitParam(name = "changeType", value = "增加减少 0收入 1支出", required = false, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "linkModel", value = "记录类型 1充值", required = false, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "linkSn", value = "关联订单号(暂只支持精准搜索）", required = false, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "fromDate", value = "记录搜索开始时间", required = false, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "toDate", value = "记录搜索结束时间", required = false, dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "start", value = "页码（不传默认1）", required = false, dataTypeClass = Integer.class, paramType = "query"),
            @ApiImplicitParam(name = "limits", value = "每页条数（不传默认10）", required = false, dataTypeClass = Integer.class, paramType = "query"),
    })
    @GetMapping("/searchBalanceRecordList")
    public TableDataInfo searchBalanceRecordList(@ApiIgnore @AuthMember MemberDO member) {
        MemberBalanceRecordSearchVO memberBalanceRecordSearchVO = new MemberBalanceRecordSearchVO();
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("changeType"))) {
            memberBalanceRecordSearchVO.setChangeType(ServletUtils.getParameterToInt("changeType"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("linkModel"))) {
            memberBalanceRecordSearchVO.setLinkModel(ServletUtils.getParameterToInt("linkModel"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("linkSn"))) {
            memberBalanceRecordSearchVO.setLinkSn(ServletUtils.getParameter("linkSn"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("fromDate"))
                && StringUtils.isNotEmpty(ServletUtils.getParameter("toDate"))) {
            memberBalanceRecordSearchVO.setFromDate(ServletUtils.getParameter("fromDate"));
            memberBalanceRecordSearchVO.setToDate(ServletUtils.getParameter("toDate"));
        }
        memberBalanceRecordSearchVO.setShopId(member.getShopId());
        HashMap<String, Object> params = new HashMap<>();
        params.put("start", ServletUtils.getParameterToInt("start", 1));
        params.put("limits", ServletUtils.getParameterToInt("limits", 10));
        params.put("orderBy", ServletUtils.getParameter("orderBy", "create_time desc"));
        BaseEntity pageVo = new BaseEntity();
        pageVo.setParams(params);
        startPage(pageVo);
        return getDataTable(memberService.searchBalanceRecordList(memberBalanceRecordSearchVO));
    }

    @ApiOperation(value = "获取会员消费记录", notes = "获取会员消费记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登录密钥", required = true, paramType = "header"),
            @ApiImplicitParam(name = "changeType", value = "增加减少 0收入 1支出", required = false, paramType = "query"),
            @ApiImplicitParam(name = "linkModel", value = "记录类型 1充值", required = false, paramType = "query"),
            @ApiImplicitParam(name = "linkSn", value = "关联订单号(暂只支持精准搜索）", required = false, paramType = "query"),
            @ApiImplicitParam(name = "fromDate", value = "记录搜索开始时间", required = false, paramType = "query"),
            @ApiImplicitParam(name = "toDate", value = "记录搜索结束时间", required = false, paramType = "query"),
            @ApiImplicitParam(name = "yearMonth", value = "年月查询", required = false, paramType = "query"),
            @ApiImplicitParam(name = "start", value = "页码（不传默认1）", required = false, paramType = "query"),
            @ApiImplicitParam(name = "limits", value = "每页条数（不传默认10）", required = false, paramType = "query"),
    })
    @GetMapping("/searchConsumeList")
    public TableDataInfo searchConsumeList(@ApiIgnore @AuthMember MemberDO member) {
        MemberConsumeSearchVO memberConsumeSearchVO = new MemberConsumeSearchVO();
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("changeType"))) {
            memberConsumeSearchVO.setChangeType(ServletUtils.getParameterToInt("changeType"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("linkModel"))) {
            memberConsumeSearchVO.setLinkModel(ServletUtils.getParameterToInt("linkModel"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("fromDate"))
                && StringUtils.isNotEmpty(ServletUtils.getParameter("toDate"))) {
            memberConsumeSearchVO.setFromDate(ServletUtils.getParameter("fromDate"));
            memberConsumeSearchVO.setToDate(ServletUtils.getParameter("toDate"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("yearMonth"))) {
            memberConsumeSearchVO.setYearMonth(ServletUtils.getParameter("yearMonth"));
        }
        memberConsumeSearchVO.setShopId(member.getShopId());
        memberConsumeSearchVO.setMemberId(member.getId());
        memberConsumeSearchVO.setStart(ServletUtils.getParameterToInt("start", 1));
        memberConsumeSearchVO.setLimits(ServletUtils.getParameterToInt("limits", 10));
        memberConsumeSearchVO.setOrderBy(ServletUtils.getParameter("orderBy", "create_time desc"));
        List<MemberConsumeVO> consumeList = memberService.searchConsumeList(memberConsumeSearchVO);
        int total = consumeList.size();
        TableDataInfo returnData = new TableDataInfo();
        returnData.setCode(0);
        returnData.setTotal(total);
        if (total > 0) {
            int fromIndex = (memberConsumeSearchVO.getStart() - 1) * memberConsumeSearchVO.getLimits();
            int toIndex = memberConsumeSearchVO.getStart() * memberConsumeSearchVO.getLimits();
            if (toIndex > total) {
                toIndex = total;
            }
            returnData.setRows(consumeList.subList(fromIndex, toIndex));
        }
        HashMap<String, Object> appendData = new HashMap<>();
        appendData.put("consumeTotal", memberService.getConsumeTotal(memberConsumeSearchVO));
        returnData.setAppendData(appendData);
        return returnData;
    }

    @ApiOperation(value = "积分变动记录", notes = "获取会员积分变动记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登录密钥", required = true, paramType = "header"),
            @ApiImplicitParam(name = "changeType", value = "增加减少 0收入 1支出", required = false, paramType = "query"),
            @ApiImplicitParam(name = "linkModel", value = "记录类型 1充值", required = false, paramType = "query"),
            @ApiImplicitParam(name = "linkSn", value = "关联订单号(暂只支持精准搜索）", required = false, paramType = "query"),
            @ApiImplicitParam(name = "fromDate", value = "记录搜索开始时间", required = false, paramType = "query"),
            @ApiImplicitParam(name = "toDate", value = "记录搜索结束时间", required = false, paramType = "query"),
            @ApiImplicitParam(name = "start", value = "页码（不传默认1）", required = false, paramType = "query"),
            @ApiImplicitParam(name = "limits", value = "每页条数（不传默认10）", required = false, paramType = "query"),
    })
    @GetMapping("/searchCreditRecordList")
    public TableDataInfo searchCreditRecordList(@ApiIgnore @AuthMember MemberDO member) {
        MemberCreditRecordSearchVO memberCreditRecordSearchVO = new MemberCreditRecordSearchVO();
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("changeType"))) {
            memberCreditRecordSearchVO.setChangeType(ServletUtils.getParameterToInt("changeType"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("linkModel"))) {
            memberCreditRecordSearchVO.setLinkModel(ServletUtils.getParameterToInt("linkModel"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("linkSn"))) {
            memberCreditRecordSearchVO.setLinkSn(ServletUtils.getParameter("linkSn"));
        }
        if (StringUtils.isNotEmpty(ServletUtils.getParameter("fromDate"))
                && StringUtils.isNotEmpty(ServletUtils.getParameter("toDate"))) {
            memberCreditRecordSearchVO.setFromDate(ServletUtils.getParameter("fromDate"));
            memberCreditRecordSearchVO.setToDate(ServletUtils.getParameter("toDate"));
        }
        memberCreditRecordSearchVO.setShopId(member.getShopId());
        memberCreditRecordSearchVO.setMemberId(member.getId());
        HashMap<String, Object> params = new HashMap<>();
        params.put("start", ServletUtils.getParameterToInt("start", 1));
        params.put("limits", ServletUtils.getParameterToInt("limits", 10));
        params.put("orderBy", ServletUtils.getParameter("orderBy", "create_time desc"));
        BaseEntity pageVo = new BaseEntity();
        pageVo.setParams(params);
        startPage(pageVo);
        return getDataTable(memberService.searchCreditRecordList(memberCreditRecordSearchVO));
    }

    @ApiOperation(value = "查看会员权益", notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "登录密钥", required = true, paramType = "header"),
    })
    @GetMapping("/searchVipBenefitList")
    public TableDataInfo searchVipBenefitList(@ApiIgnore @AuthMember MemberDO member) {
        List<MemberVipTypeVO> vipBenefitList = memberVipTypeService.searchVipBenefitList(member.getShopId());
        int nextIdx = 0;
        if (vipBenefitList.size() > 0) {
            int isShowProcess = 0;
            int isShowProcessDesc = 0;
            if ("Y".equals(shopConfigMapper.searchValueByKey("memberVipType.upgrade.process.switch", member.getShopId()))) {
                isShowProcess = 1;
                isShowProcessDesc = 1;
            }
            MemberDetailBO memberAsset = memberService.getAssetById(member.getId());
            for (MemberVipTypeVO one : vipBenefitList
            ) {
                nextIdx++;
                switch (MemberConstants.MemberVipTypeConditionEnum.match(one.getUpgradeCondition())) {
                    case RECHARGE:
                        one.setUpgradeDesc("充值");
                        one.setNowValue(memberAsset.getTotalRechargeAmount());
                        break;
                    case PETROL:
                        one.setUpgradeDesc("消费");
                        one.setNowValue(memberAsset.getTotalPetrolAmount());
                        break;
                    case RECHARGE_PETROL:
                        one.setUpgradeDesc("充值或消费");
                        one.setNowValue(memberAsset.getTotalPetrolAmount().add(memberAsset.getTotalRechargeAmount()));
                        break;
                    default:
                        break;
                }
                double mtn = 0.00;
                BigDecimal upgradeValue = BigDecimal.valueOf(one.getUpgradeValue());
                one.setNextName(one.getVipTypeName());
                one.setGapValue(upgradeValue.subtract(one.getNowValue()));
                if (one.getGapValue().compareTo(BigDecimal.ZERO) <= 0) {
                    //已解锁 （三种情况，第一种已解锁且不是当前等级不是这个，第二种已解锁且当前等级就是这个，第三种已解锁且达到最高等级了）
                    if (!memberAsset.getVipTypeId().equals(one.getId())) {
                        //已解锁但当前等级不是这个
                        one.setUpgradeStatus(1);
                        one.setGapValue(BigDecimal.ZERO);
                        mtn = 100.00;
                    } else {
                        //已解锁且当前等级就是这个
                        one.setUpgradeStatus(2);
                        if (nextIdx == vipBenefitList.size()) {
                            //且已经是升级值最大的一个等级
                            one.setGapValue(BigDecimal.ZERO);
                            mtn = 100.00;
                        } else {
                            upgradeValue = BigDecimal.valueOf(vipBenefitList.get(nextIdx).getUpgradeValue());
                            one.setGapValue(upgradeValue.subtract(one.getNowValue()));
                            one.setNextName(vipBenefitList.get(nextIdx).getVipTypeName());
                        }
                    }
                }
                if (0.00 == mtn) {
                    if (null == one.getUpgradeStatus()) {
                        //未解锁
                        one.setUpgradeStatus(0);
                    }
                    if (one.getNowValue().equals(BigDecimal.ZERO)) {
                        mtn = 0.00;
                    } else {
                        try {
                            mtn = one.getNowValue().multiply(BigDecimal.valueOf(100L)).divide(upgradeValue, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
                        } catch (ArithmeticException e) {
                            mtn = 0.00;
                        }
                    }
                }
                one.setProgressRate(mtn);
                one.setIsShowProgress(isShowProcess);
                one.setIsShowProgressDesc(isShowProcess);
            }
        }
        return getDataTable(vipBenefitList);
    }

    /**
     * 随机生成TOKEN
     *
     * @return
     */
    @GetMapping("/createToken3jf9312/{memberId}")
    @PassToken
    public AjaxResult createToken(@PathVariable("memberId") Long memberId) {
        MemberDO member = memberService.getMemberForToken(memberId);
        return AjaxResult.success("获取成功", JwtUtil.sign(member.getOpenid(), member.getId(), member.getShopId(), member.getId() + salt));
    }

    /**
     * 生成模拟会员
     */
//    @GetMapping("/createMember090b5a20")
//    @PassToken
//    public AjaxResult createToken() {
//        MemberDO member = new MemberDO();
//        member.setNickname("模拟用户" + NumberUtils.generateCode(4));
//        member.setAvatar("https://xrmwl.com/hg/de-ph.jpg");
//        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
//        //TODO：生成6位随机盐
//        member.setSalt(secureRandom.nextBytes(3).toHex());
//        //TODO：生成24位随机盐
//        member.setOpenid("test" + secureRandom.nextBytes(12).toHex());
//        member.setLoginTime(new Date());
//        member.setCreateTime(new Date());
//        memberMapper.insertSelective(member);
//        return AjaxResult.success("生成成功", member);
//    }
}
